//
//  UIControl+LYAdd.m
//  LYDevelopKit
//
//  Created by 李阳 on 2018/5/25.
//

#import "UIControl+LYAdd.h"
#import <objc/runtime.h>
#import "LYUIMacros.h"

LYSYNTH_DUMMY_CLASS(UIControl_Private)

@interface UIControl (Private)
@property (nonatomic, assign) BOOL ignoreEvent;
@end
@implementation UIControl (Private)
- (BOOL)ignoreEvent
{
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setIgnoreEvent:(BOOL)ignoreEvent
{
    objc_setAssociatedObject(self, @selector(ignoreEvent), @(ignoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

LYSYNTH_DUMMY_CLASS(UIControl_LYAdd)

@implementation UIControl (LYAdd)

+ (void)load
{
    SEL selA = @selector(sendAction:to:forEvent:);
    SEL selB = @selector(mySendAction:to:forEvent:);
    Method methodA =  class_getInstanceMethod(self,selA);
    Method methodB = class_getInstanceMethod(self, selB);
    BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));
    if (isAdd)
    {
        class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));
    }
    else
    {
        method_exchangeImplementations(methodA, methodB);
    }
}

- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    if (self.ignoreEvent == YES)
    {
        return;
    }
    NSTimeInterval interval = self.acceptEventInterval;
    if (interval > 0)
    {
        self.ignoreEvent = YES;
        [self performSelector:@selector(resetState)
                   withObject:nil
                   afterDelay:interval];
    }
    [self mySendAction:action to:target forEvent:event];
}

- (NSTimeInterval)acceptEventInterval
{
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setAcceptEventInterval:(NSTimeInterval)interval
{
    if (interval <= 0)
    {
        return;
    }
    objc_setAssociatedObject(self, @selector(acceptEventInterval), @(interval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


- (void)resetState
{
    [self setIgnoreEvent:NO];
}


- (void)setHitEdgeInsets:(UIEdgeInsets)hitEdgeInsets
{
    NSValue *value = [NSValue value:&hitEdgeInsets withObjCType:@encode(UIEdgeInsets)];
    objc_setAssociatedObject(self,@selector(hitEdgeInsets), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIEdgeInsets)hitEdgeInsets
{
    NSValue *value = objc_getAssociatedObject(self, _cmd);
    UIEdgeInsets edgeInsets;
    [value getValue:&edgeInsets];
    return value ? edgeInsets : UIEdgeInsetsZero;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    //如果 button 边界值无变化  失效 隐藏 或者透明 直接返回
    if(UIEdgeInsetsEqualToEdgeInsets(self.hitEdgeInsets, UIEdgeInsetsZero) ||
       !self.enabled ||
       self.hidden ||
       self.alpha == 0 )
    {
        return [super pointInside:point withEvent:event];
    }
    else
    {
        CGRect relativeFrame = self.bounds;
        CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.hitEdgeInsets);
        return CGRectContainsPoint(hitFrame, point);
    }
}

@end
